package com.framework.workflow.util;

import com.framework.workflow.constant.DataDict;
import com.framework.workflow.dto.NodeProperty;
import com.framework.workflow.params.CompleteParam;
import com.framework.workflow.params.StartParam;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.common.engine.impl.el.ExpressionManager;
import org.flowable.engine.impl.bpmn.behavior.ErrorEndEventActivityBehavior;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.impl.util.CommandContextUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author zzg
 * @date 2025-6-9 13:54
 */
public class WorkflowHelper {
    public static boolean isStartNode(Process process, String taskDefKey) {
        FlowElement flowElement = process.getInitialFlowElement();
        // 任务开始节点
        flowElement = ((FlowNode) flowElement).getOutgoingFlows().get(0).getTargetFlowElement();
        FlowElement taskElement = process.getFlowElement(taskDefKey, true);
        return flowElement.getId().equals(taskElement.getId());
    }

    public static NodeProperty next(Process process, String taskDefKey, Map<String, Object> variables) {
        FlowElement flowElement;
        if (StringUtils.isNotBlank(taskDefKey)) {
            flowElement = process.getFlowElement(taskDefKey, true);
        } else {
            // 开始
            flowElement = process.getInitialFlowElement();
            // 任务开始节点
            flowElement = ((FlowNode) flowElement).getOutgoingFlows().get(0).getTargetFlowElement();
        }
        FlowNode startActivity = (FlowNode) flowElement;
        List<SequenceFlow> flowList = startActivity.getOutgoingFlows();
        NodeProperty nodeProperty = new NodeProperty();
        loopNext(flowList, variables, nodeProperty);

        if (nodeProperty.isFireEvent()) {
            List<BoundaryEvent> boundaryEvents = ((SubProcess)flowElement.getParentContainer()).getBoundaryEvents();
            if (null != boundaryEvents && boundaryEvents.size() > 0) {
                BoundaryEvent event = boundaryEvents.get(0);
                flowList = event.getOutgoingFlows();
                nodeProperty.setFireEvent(false);
                loopNext(flowList, variables, nodeProperty);
            }
        }

        return nodeProperty;
    }

    public static void loopNext(List<SequenceFlow> flowList, Map<String, Object> variables, NodeProperty nodeProperty) {
        for (SequenceFlow flow : flowList) {
            FlowNode el = (FlowNode) flow.getTargetFlowElement();
            if (el instanceof UserTask) {
                UserTask t = (UserTask) el;
                nodeProperty.setTaskDefKey(t.getId());
                Object behavior = t.getBehavior();
                if (behavior instanceof ParallelMultiInstanceBehavior) {
                    nodeProperty.setMulti(true);
                }
                String assignee = t.getAssignee();
                assignee = getAssignee(assignee);
                // 指定了处理人, 分组无效
                if (!StringUtils.isNotBlank(assignee)) {
                    List<String> groups = t.getCandidateGroups();
                    nodeProperty.setGroups(groups);
                    List<String> users = t.getCandidateUsers();
                    nodeProperty.setUsers(users);
                }
                nodeProperty.setAssignee(assignee);
            } else if (el instanceof ParallelGateway) {
                // 并行网关， 每条路都会走
                ParallelGateway gateway = (ParallelGateway) el;
                List<SequenceFlow> nextFlowList = gateway.getOutgoingFlows();
                loopNext(nextFlowList, variables, nodeProperty);
            } else if (el instanceof Gateway) {
                Gateway gateway = (Gateway) el;
                List<SequenceFlow> nextFlowList = gateway.getOutgoingFlows();
                List<SequenceFlow> chooseList = new ArrayList<>();
                for (SequenceFlow o : nextFlowList) {
                    String expression = o.getConditionExpression();
                    if (isCondition(expression, variables)) {
                        chooseList.add(o);
                        break;
                    }
                }
                loopNext(chooseList, variables, nodeProperty);
            } else if (el instanceof Task) {
                Task task = (Task) el;
                List<SequenceFlow> nextFlowList = task.getOutgoingFlows();
                loopNext(nextFlowList, variables, nodeProperty);
            } else if (el instanceof EndEvent) {
                Object behavior = el.getBehavior();
                if (behavior instanceof ErrorEndEventActivityBehavior) {
                    nodeProperty.setFireEvent(true);
                } else {
                    nodeProperty.setEnd(true);
                }
            }
        }
    }

    private static boolean isCondition(String expression, Map<String, Object> variables) {
        if (expression == null || expression.trim().isEmpty()) {
            // 空表达式视为true
            return true;
        }

        try {
            // 获取表达式管理器
            ExpressionManager expressionManager = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager();
            // 创建表达式
            Expression conditionExpression = expressionManager.createExpression(expression);

            // 使用Flowable提供的ExecutionEntity实现
            ExecutionEntity execution = new ExecutionEntityImpl();
            execution.setVariables(variables);

            // 评估表达式
            Object result = conditionExpression.getValue(execution);

            // 将结果转换为布尔值
            if (result instanceof Boolean) {
                return (Boolean) result;
            } else if (result instanceof String) {
                return Boolean.parseBoolean((String) result);
            }
            return result != null;
        } catch (Exception e) {
            // 表达式解析或执行出错视为不满足条件
            return false;
        }
    }

    private static String getExtendAttribute(Map<String, List<ExtensionAttribute>> fileMap, String mainKey, String childKey) {
        List<ExtensionAttribute> extensionElements = fileMap.get(mainKey);
        String value = StringUtils.EMPTY;
        if (null!=extensionElements && extensionElements.size() > 0) {
            for (ExtensionAttribute item : extensionElements) {
                String name = item.getName();
                if (childKey.equals(name)) {
                    value = item.getValue();
                }
            }
        }

        return value;
    }

    public static String getExtendAttribute(Map<String, List<ExtensionAttribute>> fileMap, String key) {
        return getExtendAttribute(fileMap, key, key);
    }

    public static CompleteParam getStartModel(StartParam bomModel) {
        CompleteParam model = new CompleteParam();
        List<String> list = bomModel.getSelectAssigneeList();
        model.setSelectAssigneeList(list);
        model.setIsReject(DataDict.WfRejectStatus.AGREE.toString());
        model.setDescription("发起流程");
        return model;
    }

    private static String getAssignee(String assignee) {
        if (StringUtils.isBlank(assignee)) {
            return null;
        }
        String prefix = "${";
        String suffix = "}";
        assignee = assignee.trim();
        // 如果是变量返回null
        if (assignee.startsWith(prefix) && assignee.endsWith(suffix)) {
            return null;
        }

        return assignee;
    }
}
